package com.yenlien.traceyun.business.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.business.bean.RestURL;
import com.yenlien.traceyun.business.controller.from.WarehouseForm;
import com.yenlien.traceyun.business.controller.response.BaseSoilView;
import com.yenlien.traceyun.business.dao.*;
import com.yenlien.traceyun.business.entity.*;
import com.yenlien.traceyun.business.interceptor.UserAuthUtil;
import com.yenlien.traceyun.business.service.rest.usercenter.CompanyRestService;
import com.yenlien.traceyun.business.service.rest.usercenter.FileRestService;
import com.yenlien.traceyun.common.utils.HttpUtil;
import com.yenlien.traceyun.webase.exception.BusinessException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.*;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: bigwangy@sina.com
 * @create: 2020-11-24
 * @description:
 **/

@Service
public class BaseSoilService {

    @Autowired
    private BaseSoilDao baseSoilDao;

    @Autowired
    private FileRestService fileRestService;

    @Autowired
    private BaseSoilEquipmentDao baseSoilEquipmentDao;

    @Value("${traceyun.app.id}")
    private String appId;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private EquipmentDao equipmentDao;

    @Autowired
    private CompanyRestService companyRestService;

    @Autowired
    private WarehousePartDao wrehousePartDao;

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private CHbaseSoilDao cHbaseSoilDao;



    /**
     * 保存
     *
     * @param baseSoil
     * @param files
     * @return
     */
    @Transactional
    public BaseSoil save(WarehouseForm baseSoil, List<MultipartFile> files, HttpServletRequest request) throws Exception {
        baseSoil.setAppId(appId);
        if (StringUtils.isEmpty(baseSoil.getId())) {
            fileRestService.upload(null, baseSoil, files);
        } else {
            fileRestService.upload(baseSoilDao.findById(baseSoil.getId()).get(), baseSoil, files);
        }
        BaseSoil baseSoil1 = baseSoil.getBaseSoil();
        baseSoil1.setCompanyId(UserAuthUtil.getLoginUser().getCompanyId());
        // 添加企业新建基地的数据权限
        if (1 == baseSoil1.getType()) {
            // 如果该企业的新建过的基地数已经达到了最大值则不允许新建
            int basesNum = getDataByType(baseSoil1.getCompanyId(), "basesNum");
            // 获取该企业已经有的基地个数
            int baseNum = baseSoilDao.getNum(baseSoil1.getCompanyId(), 1);
            if (baseNum >= basesNum) {
                throw new BusinessException("该企业的基地数已达最大,不能再新建,最大限制:" + basesNum + ", 已有基地数: " + baseNum);
            }
        }
        // 添加企业新建地块的数据权限
        if (2 == baseSoil1.getType()) {
            int soilNumMax = getDataByType(baseSoil1.getCompanyId(), "soilNum");
            // 获取该企业已经有的基地个数
            int soilNum = baseSoilDao.getNum(baseSoil1.getCompanyId(), 2);
            if (soilNum >= soilNumMax) {
                throw new BusinessException("该企业的地块数已达最大,不能再新建,最大限制:" + soilNumMax + ", 已有地块数: " + soilNum);
            }
        }
        // 处理多余 []

        BaseSoil p = baseSoilDao.save(baseSoil1);
        //如果是仓库
        if (baseSoil.getType() == 3) {
            warehouseService.save(baseSoil.getWarehouse(), baseSoil.getWarehouseParts(), p);
            wrehousePartDao.deleteByBaseSoilId(baseSoil.getId());       //先删除再添加
            //添加仓位
            List<WarehousePart> warehouseParts = baseSoil.getWarehouseParts();
            List<WarehousePart> partList = new ArrayList<>();
            for (WarehousePart warehousePart : warehouseParts) {
                WarehousePart warehousePart2 = new WarehousePart();
                warehousePart2.setName(warehousePart.getName());
                warehousePart2.setUserId(baseSoil.getUserId());
                warehousePart2.setCreatetime(new Date());
                warehousePart2.setCompanyId(baseSoil.getCompanyId());
                warehousePart2.setBaseSoilId(p.getId());
                partList.add(warehousePart2);
            }
            wrehousePartDao.saveAll(partList);
        }
        if (baseSoil.getType() == 6 || baseSoil.getType() == 7 || baseSoil.getType() == 8 || baseSoil.getType() == 9 || baseSoil.getType() == 10 || baseSoil.getType() == 11) {
            // type = 6 才是绑定气象设备  新建地块上的图标后进行绑定   type=7是绑定摄像头设备
            String soilId1 = baseSoil1.getId(); //新建图标后获取图标(点)的ID  一个点对应一个设备
            if (soilId1 == null || "".equals(soilId1)) {
                throw new BusinessException("500", "新建点失败");
            }
            // 已绑定的设备不能再绑定
            String equipmentId = request.getParameter("principalId");
            List<BaseSoilEquipment> byEquipmentId = baseSoilEquipmentDao.findByEquipmentId(equipmentId);
            if (byEquipmentId != null && byEquipmentId.size() > 0) {
                throw new BusinessException("500", "该设备已绑定了一个点,不能再进行绑定");
            }

//            Equipment equipment = JSONObject.parseObject(request.getParameter("equipment"), Equipment.class);
//            equipmentDao.save(equipment);


            BaseSoilEquipment soilEquipment = new BaseSoilEquipment();
            soilEquipment.setBaseSoilId(soilId1);
            // 绑定地块
            soilEquipment.setMassifId(baseSoil.getMassifId());
            soilEquipment.setType(request.getParameter("equType"));
            soilEquipment.setEquipmentId(equipmentId);
//            soilEquipment.setEquipmentId(equipment.getId());
            soilEquipment.setCoordinate(request.getParameter("coordinate"));
            soilEquipment.setEquipmentName(request.getParameter("principalName"));
            soilEquipment.setCompanyId(UserAuthUtil.getLoginUser().getCompanyId());
            soilEquipment.setAppId(appId);
            Equipment equipment = equipmentDao.findById(equipmentId);
            equipment.setCoordinate(soilEquipment.getCoordinate());
            equipmentDao.save(equipment);
            if (soilEquipment.getEquipmentId() == null || "".equals(soilEquipment.getEquipmentId())) {
                throw new BusinessException("500", "缺少设备ID");
            }
            baseSoilEquipmentDao.save(soilEquipment);
            if (soilEquipment.getId() == null || "".equals(soilEquipment.getId())) {
                throw new BusinessException("500", "新建点时与设备绑定失败");
            }
        }
        return baseSoil;
    }



    public void addCHBaseSoil(CHBasesoil chBasesoil, List<MultipartFile> files){
        String upload = fileRestService.upload(files);
        chBasesoil.setImg(upload);
        if(StringUtils.isEmpty(chBasesoil.getCompanyId())){
            chBasesoil.setCompanyId(UserAuthUtil.getLoginUser().getCompanyId());
        }
        cHbaseSoilDao.save(chBasesoil);
    }

    public Page<CHBasesoil> findCHBaseSoilByList(final CHBasesoil chBasesoil) {
        Pageable pageable = PageRequest.of(chBasesoil.getPage(), chBasesoil.getPageSize(), Sort.Direction.DESC, "createTime");
        return cHbaseSoilDao.findAll((Root<CHBasesoil> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            //构造查询条件
            List<Predicate> list = new ArrayList<>();
            if (!StringUtils.isEmpty(chBasesoil.getCompanyId())) {
                list.add(cb.equal(root.get("companyId"), chBasesoil.getCompanyId()));
            }
            if (!StringUtils.isEmpty(chBasesoil.getName())) {
                list.add(cb.like(root.get("name"), "%" + chBasesoil.getName() + "%"));
            }
            Predicate[] predicate = new Predicate[list.size()];
            return cb.and(list.toArray(predicate));
        }, pageable);
    }

    public CHBasesoil findCHBaseSoilById(String id) {
        return cHbaseSoilDao.findById(id).orElseThrow(() -> new BusinessException("该数据不存在"));
    }








    public int getDataByType(String companyId, String dataType) {
        List<LinkedHashMap> listMap = (ArrayList) restTemplate.getForObject(RestURL.USERCENTER + "app/getCustomAppVersion/" + companyId, JSONObject.class).get("data");
        int max = 0;
        for (LinkedHashMap map : listMap) {
            max += (int) map.get(dataType);
        }
        return max;
    }


    public void savewrehousePartDao() {

    }

    /**
     * 删除
     *
     * @param id
     */
    public void delete(String id) {
        baseSoilDao.ljDelete(id);
    }

    /**
     * 根据id加载所有基地基地
     *
     * @param companyId
     * @return
     */
    public List<BaseSoil> findByCompanyId(String companyId) {
        return baseSoilDao.loadByCompanyId(companyId, appId);
    }

    /**
     * 加载基地下面的地块，建筑等
     *
     * @param pid
     * @param type
     * @return
     */
    public List<BaseSoil> findByPid(String pid, int type) {
        BaseSoil baseSoil = new BaseSoil();
        baseSoil.setPid(pid);
        baseSoil.setType(type);
        baseSoil.setAppId(appId);
        return baseSoilDao.findAll(create(baseSoil));
    }



    public List<BaseSoil> getByCompId(String compId) {
        if(StringUtils.isEmpty(compId)){
            compId = UserAuthUtil.getLoginUser().getId();
        }
        List<BaseSoil> baseSoilList = baseSoilDao.findByCompanyId(compId);
        List<BaseSoil> soilList = baseSoilList.stream().filter(x -> 1 == x.getType()).collect(Collectors.toList()); // 基地
        List<BaseSoil> plotList = baseSoilList.stream().filter(x -> 2 == x.getType()).collect(Collectors.toList()); // 地块
        for(BaseSoil soil : soilList){
            List<BaseSoil> plots = new ArrayList<>();
            for(BaseSoil plot : plotList){
                if(plot.getPid().equals(soil.getId())){
                    plots.add(plot);
                }
            }
            soil.setPlotList(plots);
        }
        return soilList;
    }

    public List<BaseSoil> findByCompIdName(String compId, String name) {
        if(StringUtils.isEmpty(compId)){
            compId = UserAuthUtil.getLoginUser().getId();
        }
        List<BaseSoil> baseSoilList;
        if(StringUtils.isEmpty(name))
            baseSoilList = baseSoilDao.findByCompanyId(compId);
        else
            baseSoilList = baseSoilDao.findByCompIdName(compId, name);

        return baseSoilList.stream().filter(x -> 2 == x.getType()).collect(Collectors.toList()); // 地块
    }





    /**
     * 初始化调用接口
     *
     * @return
     */
    public List<BaseSoilView> findinitAll(String companyId) {
        List<BaseSoil> soils = baseSoilDao.loadAllByCompanyId(companyId, appId);
        List<BaseSoilView> views = new ArrayList<>();
        List<BaseSoilEquipment> bindEquipments = baseSoilEquipmentDao.findByCompanyIdAndAppId(companyId, appId);
        if (soils != null && soils.size() > 0) {
            for (BaseSoil baseSoil : soils) {
                BaseSoilView view = new BaseSoilView();
                BeanUtils.copyProperties(baseSoil, view);
                view.setSoilEquipments(getSoilId(view.getId(), bindEquipments));
                // 加一个设备序列号
                ArrayList<Equipment> equipmentList = new ArrayList<>();
                if (view.getSoilEquipments() != null && view.getSoilEquipments().size() > 0) {
                    Equipment equipment = equipmentDao.findById(view.getSoilEquipments().get(0).getEquipmentId());
                    if(equipment != null){
                        equipmentList.add(equipment);
                    }
                    if(equipmentList.size() > 0){
                        view.setSerial(equipmentList.get(0).getSerial());
                    }
                } else {
                    view.setSerial("");
                }
                for (Equipment equipment : equipmentList) {
                    if (!StringUtils.isEmpty(equipment.getAppKey()) && !StringUtils.isEmpty(equipment.getAppSecret()) && "摄像头".equals(equipment.getType())) {
                        // 获取token
                        Map<String, String> map = new HashMap<>();
                        map.put("appKey", equipment.getAppKey());
                        map.put("appSecret", equipment.getAppSecret());
                        JSONObject result = JSONObject.parseObject(HttpUtil.post("https://open.ys7.com/api/lapp/token/get", map));
                        if(!"200".equals(result.getString("code"))){
                           continue;
                        }
                        String accessToken = JSONObject.parseObject(result.get("data").toString()).get("accessToken").toString();
                        equipment.setAccessToken(accessToken);
                        view.setAccessToken(accessToken);
                        if (!StringUtils.isEmpty(equipment.getSerial())) {
                            // 判断是否在线
                            Map<String, Object> map2 = new HashMap<>();
                            map2.put("accessToken", accessToken);
                            map2.put("deviceSerial", equipment.getSerial());
                            String result2 = HttpUtil.sendPost("https://open.ys7.com/api/lapp/device/info", map2);
                            if(JSONObject.parseObject(result2).get("data") != null){
                                String status = JSONObject.parseObject(JSONObject.parseObject(result2).get("data").toString()).get("status").toString();
                                equipment.setStatus(status);
                                view.setDevStatus(status);
                            }
                        }
                    }
                }
                view.setEquipments(equipmentList);
                views.add(view);
            }
        }
        return views;
    }



    public List<BaseSoilView> findinitAll2(String companyId) {
        List<BaseSoil> soils = baseSoilDao.loadAllByCompanyId(companyId, appId);
        List<BaseSoilView> views = new ArrayList<>();
        List<BaseSoilEquipment> bindEquipments = baseSoilEquipmentDao.findByCompanyIdAndAppId(companyId, appId);
        if (soils != null && soils.size() > 0) {
            for (BaseSoil baseSoil : soils) {
                BaseSoilView view = new BaseSoilView();
                BeanUtils.copyProperties(baseSoil, view);
                view.setSoilEquipments(getSoilId(view.getId(), bindEquipments));
                // 加一个设备序列号
                ArrayList<Equipment> equipmentList = new ArrayList<>();
                if (view.getSoilEquipments() != null && view.getSoilEquipments().size() > 0) {
                    Equipment equipment = equipmentDao.findById(view.getSoilEquipments().get(0).getEquipmentId());
                    if(equipment != null){
                        equipmentList.add(equipment);
                    }
                    if(equipmentList.size() > 0){
                        view.setSerial(equipmentList.get(0).getSerial());
                    }
                } else {
                    view.setSerial("");
                }
                for (Equipment equipment : equipmentList) {
                    if (!StringUtils.isEmpty(equipment.getAppKey()) && !StringUtils.isEmpty(equipment.getAppSecret()) && "摄像头".equals(equipment.getType())) {
                        // 获取token
                        Map<String, String> map = new HashMap<>();
                        map.put("appKey", equipment.getAppKey());
                        map.put("appSecret", equipment.getAppSecret());
                        JSONObject result = JSONObject.parseObject(HttpUtil.post("https://open.ys7.com/api/lapp/token/get", map));
                        if(!"200".equals(result.getString("code"))){
                            continue;
                        }
                        String accessToken = JSONObject.parseObject(result.get("data").toString()).get("accessToken").toString();
                        equipment.setAccessToken(accessToken);
                        view.setAccessToken(accessToken);
                        if (!StringUtils.isEmpty(equipment.getSerial())) {
                            // 判断是否在线
                            Map<String, Object> map2 = new HashMap<>();
                            map2.put("accessToken", accessToken);
                            map2.put("deviceSerial", equipment.getSerial());
                            String result2 = HttpUtil.sendPost("https://open.ys7.com/api/lapp/device/info", map2);
                            if(JSONObject.parseObject(result2).get("data") != null){
                                String status = JSONObject.parseObject(JSONObject.parseObject(result2).get("data").toString()).get("status").toString();
                                equipment.setStatus(status);
                                view.setDevStatus(status);
                            }
                        }
                    }
                }
                view.setEquipments(equipmentList);
                views.add(view);
            }
        }
        return views;
    }

    /**
     * 初始化调用接口
     *
     * @return
     */
    public JSONArray initjg(String companyId) {
        JSONObject jsonObject = (JSONObject) companyRestService.getchild(companyId);
        JSONArray companies = jsonObject.getJSONArray("data");
        if (companies != null && companies.size() > 0) {
            for (int i = 0; i < companies.size(); i++) {
                JSONObject item = companies.getJSONObject(i);
                List<BaseSoilView> baseSoilViews = findinitAll(item.getString("id"));
                item.put("basesoildViews", baseSoilViews);
            }
        }
        return companies;
    }

    public JSONArray initjgPlant(String companyId) {
        JSONArray array = new JSONArray();
        JSONObject jsonObject = (JSONObject) companyRestService.plantCompany(companyId);
        JSONObject item = jsonObject.getJSONObject("data");
        List<BaseSoilView> baseSoilViews = findinitAll(item.getString("id"));
        item.put("basesoildViews", baseSoilViews);
        array.add(item);
        return array;
    }

    private List<BaseSoilEquipment> getSoilId(String soildId, List<BaseSoilEquipment> bindEquipments) {
        List<BaseSoilEquipment> baseSoilEquipments = new ArrayList<>();
        if (bindEquipments != null && bindEquipments.size() > 0) {
            for (BaseSoilEquipment baseSoilEquipment : bindEquipments) {
                if (baseSoilEquipment.getBaseSoilId().equals(soildId)) {
                    baseSoilEquipments.add(baseSoilEquipment);
                }
            }
        }
        return baseSoilEquipments;
    }

    /**
     * 根据pid，type查询全部
     *
     * @param baseSoil {pid,type}
     * @return
     */
    public Page<BaseSoil> search(BaseSoil baseSoil) {
        baseSoil.setAppId(appId);
        Pageable pageable = PageRequest.of(baseSoil.getPage(), baseSoil.getPageSize(), Sort.Direction.DESC, "createtime");
        return baseSoilDao.findAll(create(baseSoil), pageable);
    }

    /**
     * 返回所有
     *
     * @return
     */
    public List<BaseSoil> findAll() {
        BaseSoil baseSoil = new BaseSoil();
        baseSoil.setAppId(appId);
        return baseSoilDao.findAll(create(baseSoil));
    }

    /**
     * 绑定设备
     *
     * @param params
     */
    public void bindEquipment(JSONObject params, String companyId) {
        List<BaseSoilEquipment> list = new ArrayList<>();
        String soilId = params.getString("soilId");
        JSONArray equipmentIds = params.getJSONArray("equipments");
        for (int i = 0; i < equipmentIds.size(); i++) {
            BaseSoilEquipment soilEquipment = new BaseSoilEquipment();
            soilEquipment.setBaseSoilId(soilId);
            JSONObject item = equipmentIds.getJSONObject(i);
            soilEquipment.setType(item.getString("type"));
            soilEquipment.setEquipmentId(item.getString("id"));
            soilEquipment.setCoordinate(item.getString("coordinate"));
            soilEquipment.setEquipmentName(item.getString("name"));
            soilEquipment.setCompanyId(companyId);
            soilEquipment.setAppId(appId);
            list.add(soilEquipment);
        }
        if (list.size() > 0) {
            baseSoilEquipmentDao.saveAll(list);
        }
    }

    /**
     * 地块码信息
     *
     * @param id
     * @return
     */
    public JSONObject loadInfo(String id) {
        JSONObject result = new JSONObject();
        result.put("basesoil", baseSoilDao.findById(id));
        List<BaseSoilEquipment> equipmentList = baseSoilEquipmentDao.findByBaseSoilId(id);
        result.put("equipmentList", equipmentList);
        return result;
    }


    public Specification create(BaseSoil baseSoil) {
        return new Specification<BaseSoil>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<BaseSoil> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> companyId = root.get("companyId");
                //构造查询条件
                List<Predicate> list = new ArrayList<>();
                list.add(cb.equal(root.get("type"), baseSoil.getType()));
                if (!StringUtils.isEmpty(baseSoil.getCompanyId())) {
                    list.add(cb.equal(root.get("companyId"), baseSoil.getCompanyId()));
                }
                if (!StringUtils.isEmpty(baseSoil.getPid())) {
                    list.add(cb.equal(root.get("pid"), baseSoil.getPid()));
                }

                if (!StringUtils.isEmpty(baseSoil.getName())) {
                    list.add(cb.like(root.get("name"), "%" + baseSoil.getName() + "%"));
                }
                if (!StringUtils.isEmpty(baseSoil.getAppId())) {
                    list.add(cb.equal(root.get("appId"), baseSoil.getAppId()));
                }
                list.add(cb.equal(root.get("isDelete"), false));
                Predicate[] predicate = new Predicate[list.size()];
                return cb.and(list.toArray(predicate));
            }
        };
    }

    //地块数量
    public Object areaNumCount(String companyId) {
        return baseSoilDao.areaNumCount(companyId);
    }

    //公司地块总数
    public int areaNumSum(String companyId) {
        return baseSoilDao.areaNumSum(companyId);
    }

    //基地信息
    public Object userAndBaseSoil(String companyId) {
        JSONArray array = new JSONArray();

        List<Map<String, Object>> maps = baseSoilDao.userAndBaseSoil(companyId);
        if (maps.size() > 0) {
            for (Map<String, Object> map : maps) {
                JSONObject obj = new JSONObject();
                obj.put("bsAreaSum", map.get("bsAreaSum"));
                obj.put("company_id", map.get("company_id"));
                obj.put("coordinate", map.get("coordinate"));
                obj.put("id", map.get("id"));
                obj.put("name", map.get("name"));
                obj.put("phone", map.get("phone"));

                obj.put("principal_name", map.get("principal_name"));
                obj.put("username", map.get("username"));
                String soilId = map.get("id") != null ? map.get("id").toString() : "";
                if (!StringUtils.isEmpty(soilId)) {
                    List<Map<String, Object>> sumPlantArae = baseSoilDao.sumPlantArae(companyId, soilId);
                    if (sumPlantArae.size() > 0) {
                        for (Map<String, Object> mapps : sumPlantArae) {
                            if (mapps != null) {
                                if (mapps.get("plantArea") != null) {
                                    obj.put("plantAreaSum", mapps.get("plantArea"));
                                } else {
                                    obj.put("plantAreaSum", 0);
                                }
                            }

                        }

                    }
                } else {
                    obj.put("plantAreaSum", 0);
                }
                array.add(obj);
            }
        }
        return array;
    }
}
